/*
WhirlMon - Whirlpool.net forums thread monitor
Copyright (C) 2012  Lindsay Mathieson

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package org.dyndns.blackpaw.whirlmon;

import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

import org.dyndns.blackpaw.whirlmon.MainService.MainBinder;
import org.dyndns.blackpaw.whirlmon.WPThread.List;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.ListFragment;
import android.support.v4.view.MenuItemCompat;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class WatchedFragment extends ListFragment implements
		MainService.IClientBinder {

	static final String LOGTAG = "WATCHED";

	boolean mUnreadOnly = true;

	class WPThreadArrayAdapter extends ArrayAdapter<WPThread> {
		public WPThreadArrayAdapter(Context context, WPThread.List threads) {
			super(context, R.layout.watched_row_view, threads);

		}

		@Override
		public android.view.View getView(int position, View convertView,
				ViewGroup parent) {

			LayoutInflater inflater = (LayoutInflater) getContext()
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

			View listItemView = convertView;
			if (null == convertView) {
				listItemView = inflater.inflate(R.layout.watched_row_view,
						parent, false);
			}

			// Thread
			WPThread t = (WPThread) getItem(position);

			// Separator View
			boolean sectionStart = (position == 0);
			if (!sectionStart) {
				// Check previous item
				WPThread prev = (WPThread) getItem(position - 1);
				sectionStart = (t.forumId != prev.forumId);
			}
			if (sectionStart) {
				TextView viewSep = (TextView) listItemView
						.findViewById(R.id.watched_separator);
				viewSep.setVisibility(View.VISIBLE);
				viewSep.setText(t.forumName);
			}

			// Title View
			TextView viewTitle = (TextView) listItemView
		                  .findViewById(R.id.watched_title);
            viewTitle.setText(t.title);
			viewTitle.setVisibility(View.VISIBLE);
			
			// Unread Count
            TextView viewUnread = (TextView) listItemView
                    .findViewById(R.id.watched_unread);
            if (t.unread == 0)
                viewUnread.setVisibility(View.GONE);
            else
                viewUnread.setText(Integer.toString(t.unread));

			// last Name
            TextView viewLastName = (TextView) listItemView.findViewById(R.id.watched_lastname);
            viewLastName.setText(t.lastName);

			// time
            TextView viewTime = (TextView) listItemView
                    .findViewById(R.id.watched_time);
			String s = "";
			// Check for differences between server and local time
			// Service can be ahead by a few minutes which leads to odd looking
			// time strings :)
			Date d = t.lastDate;
			Date now = new Date();
			if (d.after(now))
				d = now;
			s += DateUtils.getRelativeDateTimeString(getActivity()
					.getApplicationContext(), d.getTime(),
					DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS,
					DateUtils.FORMAT_12HOUR);
			viewTime.setText(s);

			return listItemView;
		}

	}

	WPThreadArrayAdapter adaptor;

	/**
	 * The Fragment's UI is just a simple text view showing its instance number.
	 */
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		Log.i(LOGTAG, "onCreateView");
		setHasOptionsMenu(true);
		View v = inflater.inflate(R.layout.watched, container, false);
		return v;
	}

	@Override
	public void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		DoOnItemClick(l, v, position, id);
	}

	@Override
	public void onStart() {
		super.onStart();
		Log.i(LOGTAG, "onStart");
	}

	@Override
	public void onStop() {
		Log.i(LOGTAG, "onStop");
		super.onStop();
	}

	@Override
	public void onDestroy() {
		Log.i(LOGTAG, "onDestroy");
		super.onDestroy();
	};

	MainBinder mBinder = null;

	/** Defines callbacks for service binding, passed to bindService() */
	private ServiceConnection mConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName className, IBinder service) {
			// We've bound to LocalService, cast the IBinder and get MainService
			// instance
			Log.i(LOGTAG, "Bound MainService");
			mBinder = (MainBinder) service;

			// Sanity check
			if (mBinder == null) {
				Log.e(LOGTAG, "Failed to acquire MainBinder!");
				return;
			}

			// Register us with service
			mBinder.SetClient(WatchedFragment.this);

			// Request Msg List
			mBinder.GetCurrent();
		}

		@Override
		public void onServiceDisconnected(ComponentName arg0) {
			Log.i(LOGTAG, "MainService Disconnected");
			mBinder = null;
		}
	};

	@Override
	public void onResume() {
		super.onResume();
		Log.i(LOGTAG, "onResume");

		// Bind to MainService
		Intent intent = new Intent(getActivity(), MainService.class);
		if (!getActivity().getApplicationContext().bindService(intent,
				mConnection, Context.BIND_AUTO_CREATE))
			Log.e(LOGTAG, "bindService failed");

		// Check preferences
		SharedPreferences sharedPrefs = PreferenceManager
				.getDefaultSharedPreferences(getActivity());
		mUnreadOnly = sharedPrefs.getBoolean("unread_only", true);

		// Register us with service
		if (mBinder != null)
			mBinder.SetClient(this);
	}

	@Override
	public void onPause() {
		Log.i(LOGTAG, "onPause");

		// Unregister us
		if (mBinder != null)
			mBinder.SetClient(null);

		// Unbind Service
		getActivity().getApplicationContext().unbindService(mConnection);

		super.onPause();
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.refresh:
			RefreshWatchedThreads();
			return true;

		case R.id.mark_all_read:
			MarkAllRead();

		default:
			return super.onOptionsItemSelected(item);
		}
	}

	private void MarkAllRead() {
		if (adaptor == null)
			return;
		if (mBinder == null)
			return;

		for (int i = 0; i < adaptor.getCount(); i++) {
			WPThread wp = adaptor.getItem(i);
			if (wp.unread > 0)
				mBinder.MarkThreadRead(wp.id);

		}
		// Update List
		mBinder.GetCurrent();
	}

	public class UnreadComparator implements Comparator<WPThread> {

		@Override
		public int compare(WPThread arg0, WPThread arg1) {
			if (arg0.unread < arg1.unread)
				return 1;
			else if (arg0.unread == arg1.unread)
				return 0;
			else
				return -1;
		}
	}

	private void UpdateWatchedThreadsUI(WPThread.List w) {
		try {
			Log.i(LOGTAG, "UpdateWatchedThreadsUI");
			SharedPreferences sharedPrefs = PreferenceManager
					.getDefaultSharedPreferences(getActivity());
			boolean unreadOnly = sharedPrefs.getBoolean("unread_only", true);

			if (!unreadOnly) {
				// Sort Unread to top
				Collections.sort(w, new UnreadComparator());
			}

			adaptor = new WPThreadArrayAdapter(getActivity(), w);
			setListAdapter(adaptor);
			adaptor.notifyDataSetChanged();
		} catch (Throwable x) {
			Log.i(LOGTAG, "UpdateWatchedThreads", x);
		}

	}

	private void RefreshWatchedThreads() {
		if (mBinder != null)
			mBinder.DoRefresh();
	}

	public void DoOnItemClick(AdapterView<?> av, View view, int i, long l) {
		// http://forums.whirlpool.net.au/forum-replies.cfm?t=1867817&p=28&#r546
		final WPThread th = adaptor.getItem(i);
		Uri uriUrl = Uri
				.parse("http://forums.whirlpool.net.au/forum-replies.cfm?t="
						+ th.id + "&p=" + th.lastPage + "&#r" + th.lastRead);
		Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uriUrl);
		startActivity(launchBrowser);

		// Update List
		if (mBinder != null) {
			mBinder.MarkThreadRead(th.id);
			mBinder.GetCurrent();
		}
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		Log.i(LOGTAG, "onCreateOptionsMenu");
		inflater.inflate(R.menu.watched_menu, menu);
		MenuItemCompat.setShowAsAction(menu.findItem(R.id.refresh),
				MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
		super.onCreateOptionsMenu(menu, inflater);
	}

	@Override
	public void UpdateWatchedThreads(List watched) {
		final WPThread.List w = watched;

		getActivity().runOnUiThread(new Runnable() {
			@Override
			public void run() {
				UpdateWatchedThreadsUI(w);
			}
		});
	}

	@Override
	public void ShowProgressBar(boolean show) {
		final boolean s = show;
		getActivity().runOnUiThread(new Runnable() {
			@Override
			public void run() {
				getActivity().setProgressBarIndeterminateVisibility(s);
			}
		});

	}
}
